﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using MantisCommon.Settings;
using MantisCommon.WebMantisConnect;

namespace MantisCommon
{
    public class MyBugtracker : Common.Bugtracker, IDisposable
    {
        public MySettingsManager Settings
        {
            get { return settings_ as MySettingsManager; }
        }

        private MantisConnect mantis_connect_ = new MantisConnect();

        public MyBugtracker(MySettingsManager settings)
            : base(settings)
        {
            SetupConnection(false);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing && null != mantis_connect_)
                mantis_connect_.Dispose();
        }

        public void Dispose()
        {
            this.Dispose(true);

            GC.SuppressFinalize(this);
        }

        #region Connection
        private bool SetupConnection(bool showMessage)
        {
            try
            {
                System.Net.ServicePointManager.Expect100Continue = false;

                mantis_connect_.Url = Settings.Url;
                mantis_connect_.Credentials = new System.Net.NetworkCredential(Settings.HTTPUsername, Settings.HTTPPassword);
                mantis_connect_.AllowAutoRedirect = true;
            }
            catch (UriFormatException e)
            {
                if (showMessage)
                    System.Windows.Forms.MessageBox.Show(e.Message, "Invalid URL", System.Windows.Forms.MessageBoxButtons.OK);

                return false;
            }

            return true;
        }

        private bool ValidateServerURL()
        {
            try
            {
                GetVersionNumber();
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
                return false;
            }

            return true;
        }

        #endregion Connection

        #region Project Operation
        public List<String> GetProjectsList()
        {
            List<String> name_list = new List<string>();

            FeedProjectList(GetProjects(), ref name_list);

            return name_list;
        }

        public int ProjectAdd(String project_name, String project_description)
        {
            ProjectData project = new ProjectData();

            project.name = project_name;
            project.description = project_description;

            mantis_connect_.mc_project_add(Settings.Username, Settings.Password, project);

            return 0;
        }

        public void ProjectDelete(String project_name)
        {
            String project_id = GetProjectID(project_name);

            if (!String.IsNullOrEmpty(project_id))
                mantis_connect_.mc_project_delete(Settings.Username, Settings.Password, project_id);
        }

        public void ProjectEdit(String old_project_name, String new_project_name, String project_description)
        {
            String project_id = GetProjectID(old_project_name);

            if (!String.IsNullOrEmpty(project_id))
            {
                ProjectData project = GetProjectData(old_project_name);

                project.name = new_project_name;
                project.description = project_description;

                mantis_connect_.mc_project_update(Settings.Username, Settings.Password, project_id, project);
            }
        }

        #region Project
        public ProjectData[] GetProjects()
        {
            return mantis_connect_.mc_projects_get_user_accessible(Settings.Username, Settings.Password);
        }

        private void FeedProjectList(ProjectData[] projects, ref List<String> name_list)
        {
            foreach (ProjectData p in projects)
            {
                name_list.Add(p.name);

                FeedProjectList(p.subprojects, ref name_list);
            }
        }

        public String GetProjectID(String projectName)
        {
            ProjectData pd = GetProjectData(projectName);

            if (null != pd)
                return pd.id;

            return null;
        }

        public ProjectData GetProjectData(String projectName)
        {
            return GetProjectData(GetProjects(), projectName);
        }

        public ProjectData GetProjectData(ProjectData[] projects, String projectName)
        {
            if (projects == null || string.IsNullOrEmpty(projectName))
                return null;

            foreach (ProjectData project in projects)
            {
                if (project.name.ToUpperInvariant() == projectName.ToUpperInvariant())
                {
                    return project;
                }

                ProjectData result = GetProjectData(project.subprojects, projectName);

                if (null != result)
                    return result;
            }

            return null;
        }
        #endregion Project
        #endregion Project Operation

        public Bugtracker.dsData.dtIssueDataDataTable GetIssuesList()
        {
            return GetIssuesList(Settings.ProjectName);
        }

        public Bugtracker.dsData.dtIssueDataDataTable GetIssuesList(string project_name)
        {
            Bugtracker.dsData.dtIssueDataDataTable result = new Bugtracker.dsData.dtIssueDataDataTable();

            IssueHeaderData[] issues = mantis_connect_.mc_project_get_issue_headers(Settings.Username, Settings.Password, GetProjectID(Settings.ProjectName), "0", "0");

            foreach (var issue in issues)
            {
                Bugtracker.dsData.dtIssueDataRow row = result.NewdtIssueDataRow();

                row.IssueID = issue.id;
                row.IssueSummary = issue.summary;

                result.AdddtIssueDataRow(row);
            }

            return result;
        }

        public Bugtracker.dsData.dtIssueDataDataTable GetIssuesList(string project_name, string targeted_milestone)
        {
            throw new NotImplementedException();

            // We need to set or reset filter before calling
            // Once done,  GetIssuesList(string project_name) will call this function
        }

        #region Version
        public String GetVersion()
        {
            return "Mantis Version " + GetVersionNumber();
        }

        public String GetVersionNumber()
        {
            return mantis_connect_.mc_version();
        }
        #endregion Version

        protected override void SetSteps()
        {
            validation_steps_texts_ = new string[] { "Validating URL format", "Validating Mantis Server", "Validating Username/Password", "Validating Project" };
        }

        protected override bool RunCurrentStep(int current_step)
        {
            if (current_step == 0)
            {
                if (!SetupConnection(true))
                    return false;
            }
            else if (current_step == 1)
            {
                if (!ValidateServerURL())
                    return false;
            }
            else if (current_step == 2)
            {
                GetProjects();
            }
            else if (current_step == 3)
            {
                String tmp = GetProjectID(Settings.ProjectName);

                if (String.IsNullOrEmpty(tmp))
                    return false;
            }

            return true;
        }

        public bool ConnectionTest()
        {
            validation_steps_texts_ = new string[] { "Validating URL format", "Validating Mantis Server", "Validating Username/Password" };
            return ValidateSettings(new Common.RunTestCallback(RunConnectionTestStep));
        }

        protected bool RunConnectionTestStep(int current_step)
        {
            if (current_step == 0)
            {
                if (!SetupConnection(true))
                    return false;
            }
            else if (current_step == 1)
            {
                if (!ValidateServerURL())
                    return false;
            }
            else if (current_step == 2)
            {
                GetProjects();
            }
        
            return true;
        }

        public bool IssueExists(string bugID)
        {
            return mantis_connect_.mc_issue_exists(Settings.Username, Settings.Password, bugID);
        }

        public bool IssueNoteAdd(string bugId, string note)
        {
            if (!IssueExists(bugId))
                return false;

            IssueNoteData ind = new IssueNoteData();

            ind.text = note;

            mantis_connect_.mc_issue_note_add(Settings.Username, Settings.Password, bugId, ind);

            return true;
        }

        public bool IssueCheckinAdd(string bugId, string note, bool fix)
        {
            if (!IssueExists(bugId))
                return false;

            mantis_connect_.mc_issue_checkin(Settings.Username, Settings.Password, bugId, note, fix);

            return true;
        }
    }
}
